/*
 * @(#)ImageUtility.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.image;

import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Vector;

import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;

import com.dcivision.framework.Utility;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.SeekableOutputStream;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.TIFFEncodeParam;

/**
  ImageUtility.java

  <p>This class is for utility functions of image processing.<p>

    @author          Rollo Chan
    @company         DCIVision Limited
    @creation date   04/01/2004
    @version         $Revision: 1.17 $
*/

public class ImageUtility {

  public static final String REVISION = "$Revision: 1.17 $";

  public final static int WIN_WIDTH = 937;
  public final static int WIN_HEIGHT = 577;

  public void combineTiff(String[] inFilenames, OutputStream output) throws Exception {
    if (inFilenames == null || inFilenames.length == 0) {
      return;
    }

    RenderedImage mainRendImg = null;
    Vector sources = new Vector();
    for (int i = 0; i < inFilenames.length; i++) {
      if(!Utility.isEmpty(inFilenames[i])){
        RenderedImage[] input = readImageFile(inFilenames[i]);
        for (int j = 0; j < input.length; j++) {
          if (mainRendImg == null) {
            mainRendImg = input[j];
          } else {
            sources.add(input[j]);
          }
        }
      }
    }

    TIFFEncodeParam myTIFFparms = new TIFFEncodeParam();
    myTIFFparms.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
    if (sources.size() > 0) {
      myTIFFparms.setExtraImages(sources.iterator());
    }
    ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", output, myTIFFparms);
    encoder.encode(mainRendImg);
    output.close();
  }

  public RenderedImage[] readImageFile(String filename) throws Exception {
    File file = new File(filename);
    SeekableStream ss = new FileSeekableStream(file);
    String fileType = "tiff";
    if (filename.toLowerCase().endsWith("tiff") || filename.toLowerCase().endsWith("tif")) {
      fileType = "tiff";
    } else if (filename.toLowerCase().endsWith("jpeg") || filename.toLowerCase().endsWith("jpg")) {
      fileType = "jpeg";
    } else if (filename.toLowerCase().endsWith("gif")) {
      fileType = "gif";
    } else if (filename.toLowerCase().endsWith("png")) {
      fileType = "png";
    } else if (filename.toLowerCase().endsWith("bmp")) {
      fileType = "bmp";
    }
    ImageDecoder decoder = ImageCodec.createImageDecoder(fileType, ss, null);
    int numPages = 1;
    if (fileType.equals("tiff")) {
      numPages = decoder.getNumPages();
    }
    RenderedImage image[] = new RenderedImage[numPages];
    for (int i = 0; i < numPages; i++) {
      image[i] = decoder.decodeAsRenderedImage(i);
    }
    return image;
  }

  public int getNumOfPage(String filename) throws Exception {
    File file = new File(filename);
    SeekableStream ss = new FileSeekableStream(file);
    String fileType = "tiff";
    if (filename.toLowerCase().endsWith("tiff") || filename.toLowerCase().endsWith("tif")) {
      fileType = "tiff";
    } else if (filename.toLowerCase().endsWith("jpeg") || filename.toLowerCase().endsWith("jpg")) {
      fileType = "jpeg";
    } else if (filename.toLowerCase().endsWith("gif")) {
      fileType = "gif";
    } else if (filename.toLowerCase().endsWith("png")) {
      fileType = "png";
    } else if (filename.toLowerCase().endsWith("bmp")) {
      fileType = "bmp";
    }
    ImageDecoder decoder = ImageCodec.createImageDecoder(fileType, ss, null);
    int numPages = 1;
    if (fileType.equals("tiff")) {
      numPages = decoder.getNumPages();
    }
    ss.close();
    return(numPages);
  }

  public void renderedImageToJPEG(String filename, int pageNo, OutputStream output) throws Exception {
    this.renderedImageToJPEG(filename, pageNo, output, 0, 1.0F);
  }

  public void renderedImageToJPEG(String filename, int pageNo, OutputStream output, int rotateDegree) throws Exception {
    this.renderedImageToJPEG(filename, pageNo, output, rotateDegree, 1.0F);
  }

  public void renderedImageToJPEG(String filename, int pageNo, OutputStream output, float scaleFactor) throws Exception {
    this.renderedImageToJPEG(filename, pageNo, output, 0, scaleFactor);
  }

  public void renderedImageToJPEG(String filename, int pageNo, OutputStream output, int rotateDegree, float scaleFactor) throws Exception {
    RenderedImage image[] = readImageFile(filename);
    if (image != null) {
      JPEGEncodeParam encodeParam = new JPEGEncodeParam();
      encodeParam.setQuality(0.25F);
      ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", output, encodeParam);
      PlanarImage op = PlanarImage.wrapRenderedImage(image[pageNo]);
      RenderingHints rh = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      rh.add(new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY));
      rh.add(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

      // Create the parameter block and add the interpolation to it
      if (rotateDegree != 0) {
        float angle = (float)((float)rotateDegree * (Math.PI/180.0F));
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(PlanarImage.wrapRenderedImage(image[pageNo])); // The source image
        pb.add(0.0F); // The x origin to rotate about
        pb.add(0.0F); // The y origin to rotate about
        pb.add(angle); // The rotation angle in radians
        pb.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); // The interpolation method

        // Create the rotation operation and include the parameter block
        op = PlanarImage.wrapRenderedImage(JAI.create("rotate", pb, rh));
      }

      if (scaleFactor != 1.0F) {
        if (scaleFactor < 0.0F) {
          if (scaleFactor == -1.0F) {
            scaleFactor = (float)((float)WIN_WIDTH / (float)op.getWidth());
          } else if (scaleFactor == -2.0F) {
            scaleFactor = (float)((float)WIN_HEIGHT / (float)op.getHeight());
          } else {

          }
        }

        ParameterBlock pb1 = new ParameterBlock();
        pb1.addSource(op); // The source image
        pb1.add(scaleFactor); // The xScale
        pb1.add(scaleFactor); // The yScale
        pb1.add(0.0F); // The x translation
        pb1.add(0.0F); // The y translation
        pb1.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); // The interpolation

        // Create the scale operation and include the parameter block
        op = PlanarImage.wrapRenderedImage(JAI.create("scale", pb1, rh));
      }

      encoder.encode(op);
    }
  }

  public static void main(String[] argv) throws Exception {
/*
    String filename = argv[0];
    FileOutputStream fos = new FileOutputStream(argv[1]);
    Test t = new Test();
    t.outputImage(filename, fos, argv[2]);
    fos.close();
*/
    String outputFile = "out.tif";
    OutputStream output = new SeekableOutputStream(new RandomAccessFile(outputFile, "rw"));
    ImageUtility t = new ImageUtility();

    t.combineTiff(argv, output);
  }

}
